//
// Created by antler on 2018/12/21.
//

#include "UIViewUtils.h"
#include "UI.h"

static jmethodID methodID_UIView_getID = nullptr;
static jmethodID methodID_UIView_getType = nullptr;
static jmethodID methodID_UIView_subviewsCount = nullptr;
static jmethodID methodID_UIView_getSubview = nullptr;
static jmethodID methodID_UIView_addSubview = nullptr;
static jmethodID methodID_UIView_removeSubview = nullptr;
static jmethodID methodID_UIView_removeFromParent = nullptr;
static jmethodID methodID_UIView_setActionCallback = nullptr;
static jmethodID methodID_UIView_removeAllActionCallback = nullptr;
static jmethodID methodID_UIView_toJson = nullptr;
static jmethodID methodID_UIView_setAttr = nullptr;
static jmethodID methodID_UIView_setStyle = nullptr;
static jmethodID methodID_UIView_setPseudoStyle = nullptr;

namespace UIViewUtils {

    std::string getID(jobject juiview) {
        std::string id;

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_getID == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_getID = env->GetMethodID(localClassUIView,
                                                         METHOD_NAME_UIVIEW_GETID,
                                                         METHOD_SIG_UIVIEW_GETID);
            }

            if (!methodID_UIView_getID) {
                assert(0);
                break;
            }

            jstring result = (jstring) env->CallObjectMethod(juiview, methodID_UIView_getID);
            id = LuaJavaHelper::jstring2string(env, result);

        } while (0);
        return id;
    }

    int getType(jobject juiview) {
        int type = UI::TYPE::UNKNOWN;

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_getType == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_getType = env->GetMethodID(localClassUIView,
                                                           METHOD_NAME_UIVIEW_GETTYPE,
                                                           METHOD_SIG_UIVIEW_GETTYPE);
            }

            if (!methodID_UIView_getType) {
                assert(0);
                break;
            }

            type = env->CallIntMethod(juiview, methodID_UIView_getType);

        } while (0);
        return type;
    }

    int subviewsCount(jobject juiview) {
        int subviewsCount = 0;

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_subviewsCount == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_subviewsCount = env->GetMethodID(localClassUIView,
                                                                 METHOD_NAME_UIVIEW_SUBVIEWSCOUNT,
                                                                 METHOD_SIG_UIVIEW_SUBVIEWSCOUNT);
            }

            if (!methodID_UIView_subviewsCount) {
                assert(0);
                break;
            }

            subviewsCount = env->CallIntMethod(juiview, methodID_UIView_subviewsCount);

        } while (0);
        return subviewsCount;
    }

    jobject getSubview(jobject juiview, int index) {
        jobject juisubview = nullptr;

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_getSubview == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_getSubview = env->GetMethodID(localClassUIView,
                                                              METHOD_NAME_UIVIEW_GETSUBVIEW,
                                                              METHOD_SIG_UIVIEW_GETSUBVIEW);
            }

            if (!methodID_UIView_getSubview) {
                assert(0);
                break;
            }

            juisubview = env->CallObjectMethod(juiview, methodID_UIView_getSubview, index);

        } while (0);
        return juisubview;
    }

    void addSubview(jobject juiview, jobject juisubview, int index) {

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (!juisubview) {
                break;
            }

            if (methodID_UIView_addSubview == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_addSubview = env->GetMethodID(localClassUIView,
                                                              METHOD_NAME_UIVIEW_ADDSUBVIEW,
                                                              METHOD_SIG_UIVIEW_ADDSUBVIEW);
            }

            if (!methodID_UIView_addSubview) {
                assert(0);
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_addSubview, juisubview, index);

        } while (0);
    }

    void removeSubview(jobject juiview, int index) {

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_removeSubview == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_removeSubview = env->GetMethodID(localClassUIView,
                                                                 METHOD_NAME_UIVIEW_REMOVESUBVIEW,
                                                                 METHOD_SIG_UIVIEW_REMOVESUBVIEW);
            }

            if (!methodID_UIView_removeSubview) {
                assert(0);
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_removeSubview, index);

        } while (0);
    }

    void removeFromParent(jobject juiview) {

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_removeFromParent == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_removeFromParent = env->GetMethodID(localClassUIView,
                                                                    METHOD_NAME_UIVIEW_REMOVEFROMPARENT,
                                                                    METHOD_SIG_UIVIEW_REMOVEFROMPARENT);
            }

            if (!methodID_UIView_removeFromParent) {
                assert(0);
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_removeFromParent);

        } while (0);
    }

    void setActionCallback(jobject juiview, int action, int funID) {
        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_setActionCallback == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_setActionCallback = env->GetMethodID(localClassUIView,
                                                                     METHOD_NAME_UIVIEW_SETACTIONCALLBACK,
                                                                     METHOD_SIG_UIVIEW_SETACTIONCALLBACK);
            }

            if (!methodID_UIView_setActionCallback) {
                assert(0);
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_setActionCallback, action, funID);

        } while (0);
    }

    void removeAllActionCallback(jobject juiview) {
        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_removeAllActionCallback == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_removeAllActionCallback = env->GetMethodID(localClassUIView,
                                                                           METHOD_NAME_UIVIEW_REMOVEALLACTIONCALLBACK,
                                                                           METHOD_SIG_UIVIEW_REMOVEALLACTIONCALLBACK);
            }

            if (!methodID_UIView_removeAllActionCallback) {
                assert(0);
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_removeAllActionCallback);

        } while (0);
    }

    std::string toJson(jobject juiview) {
        std::string json;

        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_toJson == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_toJson = env->GetMethodID(localClassUIView,
                                                          METHOD_NAME_UIVIEW_TOJSON,
                                                          METHOD_SIG_UIVIEW_TOJSON);
            }

            if (!methodID_UIView_toJson) {
                assert(0);
                break;
            }

            jstring result = (jstring) env->CallObjectMethod(juiview, methodID_UIView_toJson);
            json = LuaJavaHelper::jstring2string(env, result);
        } while (0);
        return json;
    }

    void setAttr(jobject juiview, const std::string &attrs) {
        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_setAttr == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_setAttr = env->GetMethodID(localClassUIView,
                                                           METHOD_NAME_UIVIEW_SETATTR,
                                                           METHOD_SIG_UIVIEW_SETATTR);
            }

            if (!methodID_UIView_setAttr) {
                assert(0);
                break;
            }

            ScopedLocalRef<jstring> jattrs(env, env->NewStringUTF(attrs.c_str()));
            if (!jattrs) {
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_setAttr, (jstring) jattrs);

        } while (0);
    }

    void setStyle(jobject juiview, const std::string &styles) {
        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_setStyle == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_setStyle = env->GetMethodID(localClassUIView,
                                                            METHOD_NAME_UIVIEW_SETSTYLE,
                                                            METHOD_SIG_UIVIEW_SETSTYLE);
            }

            if (!methodID_UIView_setStyle) {
                assert(0);
                break;
            }

            ScopedLocalRef<jstring> jstyles(env, env->NewStringUTF(styles.c_str()));
            if (!jstyles) {
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_setStyle, (jstring) jstyles);

        } while (0);
    }

    void setPseudoStyle(jobject juiview, const std::string &pseudo, const std::string &styles) {
        do {
            JNIEnv *env = LuaJavaHelper::getInstance()->getEnv();
            if (!env) {
                break;
            }

            if (!juiview) {
                break;
            }

            if (methodID_UIView_setPseudoStyle == nullptr) {
                ScopedLocalRef<jclass> localClassUIView(env, env->GetObjectClass(juiview));
                if (!localClassUIView) {
                    break;
                }

                methodID_UIView_setPseudoStyle = env->GetMethodID(localClassUIView,
                                                                  METHOD_NAME_UIVIEW_SETPSEUDOSTYLE,
                                                                  METHOD_SIG_UIVIEW_SETPSEUDOSTYLE);
            }

            if (!methodID_UIView_setPseudoStyle) {
                assert(0);
                break;
            }

            ScopedLocalRef<jstring> jpseudo(env, env->NewStringUTF(pseudo.c_str()));
            if (!jpseudo) {
                break;
            }


            ScopedLocalRef<jstring> jstyles(env, env->NewStringUTF(styles.c_str()));
            if (!jstyles) {
                break;
            }

            env->CallVoidMethod(juiview, methodID_UIView_setPseudoStyle, (jstring) jpseudo,
                                (jstring) jstyles);

        } while (0);
    }

};